/**
 * This file is a part of qloudgen-sec. 
 * You can redistribute qloudgen-sec and/or modify it under the terms of the Lesser GNU General Public License version 3. 
 * qloudgen-sec is distributed WITHOUT ANY WARRANTY. 
 *
 * See the Lesser GNU General Public License for more details at http://www.gnu.org/licenses/. 
 **/
package org.redisson;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.redisson.cluster.ClusterConnectionManager;
import org.redisson.core.RFakeExpirable;

import com.lambdaworks.redis.RedisConnection;

abstract class ClusterRedissonFakeExpirable extends RedissonObject implements RFakeExpirable {
	final static String DELIMITER = ":";
	final ClusterConnectionManager connectionManager;

	ClusterRedissonFakeExpirable(ClusterConnectionManager connectionManager, String name) {
		super( name );
		this.connectionManager = connectionManager;
	}
	
	/**
	 * Using fake map name as prefix.
	 */
	protected String encodeKey(Object key) {
		if ( key.getClass().equals( String.class ) ) {
			return ( getName() + DELIMITER + key ); 
		}
		throw new RuntimeException( "FakeMap only support string key class type." );
	}

	/**
	 * Using fake map name as prefix.
	 */
	protected <K> K decodeKey(K key) {
		if ( key.getClass().equals( String.class ) ) {
			String tmp = ( String )key;
			return ( K )tmp.substring( tmp.indexOf( getName() + DELIMITER ) + ( getName() + DELIMITER ).length() );
		}
		throw new RuntimeException( "FakeMap only support string key class type." );
	}
	
	@Override
	public boolean expire(final Object key, final long timeToLive, final TimeUnit timeUnit) {
	    return new ClusterCommand<Boolean>( connectionManager ) {
			@Override
			public Boolean execute(RedisConnection connection) {
				return connection.expire( encodeKey( key ) , timeUnit.toSeconds( timeToLive ) );
			}
		}.run( encodeKey( key ) );
	}

	@Override
	public boolean expireAt(final Object key, final long timestamp) {
	    return new ClusterCommand<Boolean>( connectionManager ) {
			@Override
			public Boolean execute(RedisConnection connection) {
				return connection.expireat( encodeKey( key ) , timestamp );
			}
		}.run( encodeKey( key ) );
	}

	@Override
	public boolean expireAt(final Object key, final Date timestamp) {
	    return new ClusterCommand<Boolean>( connectionManager ) {
			@Override
			public Boolean execute(RedisConnection connection) {
				return connection.expireat( encodeKey( key ) , timestamp );
			}
		}.run( encodeKey( key ) );
	}

	@Override
	public boolean clearExpire(final Object key) {
	    return new ClusterCommand<Boolean>( connectionManager ) {
			@Override
			public Boolean execute(RedisConnection connection) {
				return connection.persist( encodeKey( key ) );
			}
		}.run( encodeKey( key ) );
	}

	@Override
	public long remainTimeToLive(final Object key) {
		return new ClusterCommand<Long>( connectionManager ) {
			@Override
			public Long execute(RedisConnection connection) {
				return connection.ttl( encodeKey( key ) );
			}
		}.run( encodeKey( key ) );
	}
}